package com.sdp.irrigation.utils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.StringUtils;
import com.sdp.core.bizc.exception.ApplicationException;

public class BeanUtils {

	public static Map<String, String> redisBean2Map(Object obj) {
		return redisBean2Map(obj, new String[0], new String[0]);
	}

	public static Map<String, String> redisBeanPart2Map(Object obj, String... includeFields) {
		Map<String, String> map = new HashMap<>();
		if (obj != null && includeFields != null && includeFields.length > 0) {
			Map<String, String> includeFieldMap = new HashMap<>();
			for (String fieldName : includeFields) {
				includeFieldMap.put(fieldName, "1");
			}
			try {
				Field[] fields = obj.getClass().getDeclaredFields();
				Field.setAccessible(fields, true);
				for (int i = 0, len = fields.length; i < len; i++) {
					String varName = fields[i].getName();
					if (includeFieldMap.containsKey(varName)) {
						Object o = fields[i].get(obj);
						if (o != null) {
							if (!StringUtils.isEmpty(o)) {
								map.put(varName, convertObject2String(o, fields[i].getType().getName()));
							}
						} else {
							map.put(varName, "");
						}
					}
				}
			} catch (Exception e) {
				throw new ApplicationException(e.getMessage());
			}
		} else {
			throw new ApplicationException("参数不合法！");
		}
		return map;
	}

	/**
	 * 
	 * @param obj
	 * @param canEmptyFields
	 *            可以为空的字段
	 * @param excludeFields
	 *            不转的字段名
	 * @return
	 */
	public static Map<String, String> redisBean2Map(Object obj, String[] canEmptyFields, String... excludeFields) {
		Map<String, String> map = new HashMap<>();
		if (obj != null) {
			Map<String, String> excludeFieldMap = new HashMap<>();
			if (excludeFields != null && excludeFields.length > 0) {
				for (String fieldName : excludeFields) {
					excludeFieldMap.put(fieldName, "1");
				}
			}

			Map<String, String> canEmptyFieldMap = new HashMap<>();
			if (canEmptyFields != null && canEmptyFields.length > 0) {
				for (String fieldName : canEmptyFields) {
					canEmptyFieldMap.put(fieldName, "1");
				}
			}

			try {
				Field[] fields = obj.getClass().getDeclaredFields();
				Field.setAccessible(fields, true);
				for (int i = 0, len = fields.length; i < len; i++) {
					String varName = fields[i].getName();
					if (!excludeFieldMap.containsKey(varName)) {
						Object o = fields[i].get(obj);
						if (o == null) {
							if (canEmptyFieldMap.containsKey(varName)) {
								map.put(varName, "");
							}
						} else {
							if (!StringUtils.isEmpty(o)) {
								map.put(varName, convertObject2String(o, fields[i].getType().getName()));

							} else if (canEmptyFieldMap.containsKey(varName)) {
								map.put(varName, "");
							}
						}
					}
				}
			} catch (Exception e) {
				throw new ApplicationException(e.getMessage());
			}
		}
		return map;
	}

	public static <T> T map2RedisBean(Map<String, String> map, Class<T> clazz) {
		T obj;
		try {
			obj = clazz.newInstance();
			if (map != null && map.size() > 0) {
				Field[] fields = clazz.getDeclaredFields();
				Field.setAccessible(fields, true);
				for (int i = 0, len = fields.length; i < len; i++) {
					String varName = fields[i].getName();
					if (map.containsKey(varName)) {
						fields[i].set(obj, convertString2Object(map.get(varName), fields[i].getType().getName()));
					}
				}
			}
		} catch (Exception e) {
			throw new ApplicationException(e.getMessage());
		}
		return obj;
	}

	private static Object convertString2Object(String value, String type) {
		if (value == null || "".equals(value)) {
			return null;
		} else if ("BigDecimal".equalsIgnoreCase(type) || BigDecimal.class.getName().equalsIgnoreCase(type)) {
			return new BigDecimal(value);
		} else if ("Timestamp".equalsIgnoreCase(type) || Timestamp.class.getName().equalsIgnoreCase(type)) {
			SimpleDateFormat format = null;
			Timestamp date = null;
			try {
				if ("yyyy-MM-dd HH:mm:ss.S".length() <= value.length()) {
					format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
					date = new Timestamp(format.parse(value).getTime());
				} else if ("HH:mm".length() == value.length()) {
					format = new SimpleDateFormat("HH:mm");
					date = new Timestamp(format.parse(value).getTime());
				} else if ("yyyy-MM-dd".length() == value.length()) {
					format = new SimpleDateFormat("yyyy-MM-dd");
					date = new Timestamp(format.parse(value).getTime());
				} else if ("yyyy-MM-dd HH:mm:ss".length() == value.length()) {
					format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					date = new Timestamp(format.parse(value).getTime());
				}
			} catch (Exception e) {
				throw new ApplicationException(e.getMessage());
			}
			return date;
		} else if (type.equals("java.time.LocalDateTime")) {
			return LocalDateUtil.String2LocalDateTime(value);
		} else if (type.equals("java.time.LocalDate")) {
			return LocalDateUtil.String2LocalDate(value);
		}
		return value;
	}

	private static String convertObject2String(Object o, String type) {
		String value = o.toString().trim();
		if (type.equals("java.time.LocalDateTime")) {
			value = LocalDateUtil.localDateTime2String((LocalDateTime) o);
		} else if (type.equals("java.time.LocalDate")) {
			value = LocalDateUtil.localDate2String((LocalDate) o);
		}
		return value;
	}
}
